<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title> 图片裁剪小工具</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="">
    <style>
      body{
        margin:0;
        padding: 0;
      }
      #image-canvas{
        margin-left: 100px;
        margin-top:100px;
      }

    </style>
  </head>
  <body>
   

    <div class="pic-cropper">
        <!--  源图像canvas 的图像 -->
        <canvas id="image-canvas" ></canvas>
        <button id="preview">预览</button>
        <canvas id="result-canvas" width="200" height="200"></canvas>
        <button id="export">导出</button>
        <input id="slider" type="range" />
    </div>
    <input id="img-input" type="file"/>
    <script>
    var imgInput = document.getElementById("img-input");
    var mySlider = document.getElementById("slider");
     //第一个canvas 源图像canvas
    var imgCanvas = document.getElementById("image-canvas"); //源图像canvas的尺寸为300*300
    var imgCxt = imgCanvas.getContext("2d");
    var imgWidth, imgHeight; // 图片原始宽高度
    var maskWidth = 200;
    var maskHeight = 200;
    //第二个canvas 结果图像canvas
    var resultCanvas = document.getElementById("result-canvas"); //目标canvas的尺寸为200*200
    var resultCxt = resultCanvas.getContext("2d");
    var exportBtn = document.getElementById("export");
    var currentFactor = 1; //当前的放缩倍数
    var minFactor = 1; //最小放缩倍数
    var maxFactor = 1; //最大放缩倍数
    var img = new Image(); 
    img.setAttribute('crossOrigin', 'anonymous'); // 支持图片苦于

    imgInput.onchange = function() {
      // var img = new Image();
      var imgUrl =  URL.createObjectURL(imgInput.files[0]);
      imgCanvas.setAttribute('height', 300);
    //   resultCanvas.setAttribute('height',200);
      
      getImage(imgUrl);
      
      
           
    }
    
    function drawMask (pX,pY) {
      imgCxt.fillStyle = "rgba(0,0,0,0.1)"; // 遮挡蒙层绘制，因为要遮住图片，方便绘制高亮框
      imgCxt.fillRect(0,0, img.width*currentFactor,img.height*currentFactor ); // 我让图片有一层灰色遮罩
      imgCxt.fillStyle = "rgba(250,250,250,0.4)";
      imgCxt.globalCompositeOperation = "destination-over"; //globalCompositeOperation提供canvas里图像的组合方式, destination 代表先绘制的图像（在哪个图片身上作画，那个就是目标destination）， source 代表后绘制的图像，最近绘制的图像源泉
      // imgCxt.clearRect(pX,pY,200,200);
      imgCxt.fillRect(pX,pY,200,200);  // 高亮部分绘制
  }

    function getImage(imgUrl) {
      img.src=imgUrl;
      img.onload = function() {
          
          // var originPosition = canvasOriginPosition(); //绘制图像前 获取图像的初始位置   
          imgWidth = this.width;
          imgHeight = this.height;
          calculateFactor();//绘制图像前 先初始化缩放参数
          imgCanvas.setAttribute('width', imgWidth);
          imgCanvas.setAttribute('height', imgHeight);
          // 用于截取的图片canvas 
          // resultCanvas.setAttribute('width',300);
          // resultCanvas.setAttribute('height',300);
          imgCxt.drawImage(img, 0,0, img.width*currentFactor,img.height*currentFactor);
          // 绘制蒙层和遮罩层
          imgCxt.globalCompositeOperation = "source-over"; //globalCompositeOperation提供canvas里图像的组合方式, destination 代表先绘制的图像（在哪个图片身上作画，那个就是目标destination）， source 代表后绘制的图像，最近绘制的图像源泉,source-over 也是默认值
          imgCxt.fillStyle = "rgba(0,0,0,0.1)"; // 遮挡蒙层绘制，因为要遮住图片，方便绘制高亮框
          imgCxt.fillRect(0,0, img.width*currentFactor,img.height*currentFactor ); // 我让图片有一层灰色遮罩
          imgCxt.fillStyle = "rgba(250,250,250,0.4)";
          // imgCxt.clearRect(pX,pY,200,200);
          imgCxt.fillRect(0,0,200,200);  // 高亮部分绘制 以canvas 左上角为坐标原点
          
      }
}

// 计算初始Factor,  如果图片宽度小于高度， 瘦长型， 宽度大于高度 扁平型
 function calculateFactor() {
	//竖长图片
    if(img.width<img.height) {
        minFactor = 200/img.width;//初始状态
        currentFactor =  minFactor  ;
        maxFactor = 1;
    } else {
    //扁图片
        minFactor = 200/img.height;
        currentFactor = minFactor;
        maxFactor = 1;
    }
   
    initSlider(); //初始化滑动条的min和max
}

function initSlider () {
    mySlider.min = minFactor;
    mySlider.max = maxFactor;
    mySlider.step = 0.01;
}
mySlider.oninput = function(e) {
    currentFactor =  mySlider.value;
    //每次缩放完也都要修改图片的绘制位置，缩放不改变绘制位置，所以参数置为0
    redrawImg(0,0);
}

function canvasOriginPosition () {
    calculateFactor();
    var positionX;
    var positionY;
    // if(img.width<img.height) {
    //     positionX = 100;
    //     positionY = 100 - (img.height*currentFactor - 200) /2;
    // } else {
    //     positionX = 100 - (img.width*currentFactor - 200) /2;
    //     positionY = 100;
    // }
    lastImgX = positionX;
    lastImgY = positionY;

    return({"positionX":positionX,"positionY":positionY});
}



// 重新绘制图片
function redrawImg(pX,pY) {
    //每次绘图前检查position是否没有超出区域
    var newPosition = checkPosition(pX,pY);
    // 重新设置画布宽度或者高度其实就相当于清空画布了
    imgCanvas.setAttribute('width', imgWidth);
    // console.log(newPosition);
    drawMask(newPosition.X, newPosition.Y);
    imgCxt.globalCompositeOperation = "destination-over";
    // 先绘制图片，然后再绘制蒙层呢
    imgCxt.drawImage(img,0,0,img.width*currentFactor,img.height*currentFactor);
    imgCxt.globalCompositeOperation = "destination-over";
  
}
//控制canvas拖动
var moving = false;
var lastmouseX = null;
var lastmouseY = null;

//上次移动结束,canvas画图的位置
var lastImgX = 0;
var lastImgY = 0;

// 只在imgCanvas 上添加onmousedown
imgCanvas.onmousedown=function(e) {
    moving = true;
    lastmouseX = e.clientX;
    lastmouseY = e.clientY;
    // console.log("lastmouseX=" + lastmouseX, "lastmouseY"+lastmouseY);
}

window.onmouseup = function(e) {
    
    if(moving === true) {
        moving = false;
        var newPosition = checkPosition(e.clientX - lastmouseX,e.clientY - lastmouseY)
        //每次移动完成都要改变一下上次图片绘制位置
        lastImgX = newPosition.X;
        lastImgY = newPosition.Y;
        // 手指抬起来，立刻绘制图像
        
    }

// pX 代表本次移动距离, clientX 鼠标相对于当前窗口的鼠标位置
window.onmousemove = function(e) {
  
    if(moving) {

        pX=e.clientX - lastmouseX;
        pY=e.clientY - lastmouseY;
        // console.log(pX, pY);
        // drawMask(pX, pY), pX 和 PY 就是鼠标坐标
       redrawImg(pX,pY); //移动的时候要重新绘制图像
      //  checkPosition (pX,pY)
    }
}
}



// 检查边界问题,只能在当前盒子里面，注意这个盒子是图片的当前缩放盒子
var clipPosition;
function checkPosition (pX,pY) {
    // console.log(pX,pY, lastImgX, lastImgY)
     // pX+lastImgX 就是e.clientX ，也就是当前鼠标距离视窗window 的左上方的距离
        var clientX = pX+lastImgX;
        var clientY=  pY+lastImgY ;
    //    console.log("clientX" + clientX, "lastImgX"+lastImgX )
        // 在画布上的距离，注意这里的画布canvas 因为设置了margin 所以不一样， canvas 相对window 向下向右偏移了100px 
        var x_ = clientX ;
        var y_ = clientY ;

        if(clientX < 100) {
            x_ = 0;
        }
        
        if(clientX >= img.width*currentFactor - 200) {
            x_ = img.width*currentFactor -200;
        }
        if(clientY<=100) {
            y_ = 0;
        }
        if(clientY>=  img.height*currentFactor -200) {
            y_ = img.height*currentFactor -200;
        }
    clipPosition = {"X":x_,"Y":y_};
    return(clipPosition);
}
// 预览绘制图片结果
var previewBtn = document.getElementById("preview");
    previewBtn.onclick = previewImg;

function previewImg() {
    console.log("currentFactor" +currentFactor )
    resultCxt.clearRect(0,0,300,300); // 清除目标canvas 的整体画布
    // resultCxt.drawImage(img,lastImgX,lastImgY,img.width*currentFactor,img.height*currentFactor, 0 , 0 );
    // resultCxt.drawImage(img, lastImgX  ,lastImgY, img.width*currentFactor, img.height*currentFactor)
    resultCxt.drawImage(img, clipPosition.X   ,clipPosition.Y ,img.width*currentFactor, img.height*currentFactor, 0,0,300,300)
}

exportBtn.onclick = function() {
    var url = resultCanvas.toDataURL('image/png');
    var resultLink = document.createElement("a");
    resultLink.download = "裁剪结果";
    resultLink.href = url;
    document.body.appendChild(resultLink);
    resultLink.click();
    resultLink.remove();
}


    </script>
  </body>
</html>